package kayao.client.network.message;

import kayao.client.data.SharedMemory;
import kayao.client.scene.AoIManager;
import kayao.common.Client;
import kayao.common.KayaoValues;
import kayao.common.NetworkUtils;

public class SubscriberMessage extends Message {

	protected byte []mData;
	
	protected SubscriberMessage(String targetAddress, int retries, int timeoutLength, int priority, byte[] data) 
	{
		super(targetAddress, retries, timeoutLength, priority);
		mData=data;
		createPacketData();
		
	}

	@Override
	public String type() {
		// TODO Auto-generated method stub
		return "SubscribersMessage";
	}
	/**
	 * It creates the data to be sent about the subscription.
	 */
	@Override
	public void createPacketData() {
		int counter=NetworkUtils.insertByteArrayToInt(mData, 5);
		int id=NetworkUtils.insertByteArrayToInt(mData, 9);
		byte teamid=mData[13];
		byte kingdom=mData[14];
		byte length=mData[15];
		String name="";
		for(int i=0; i<length;i++)
			name+=(char)mData[16+i];

		System.out.println("*** SubscriberMessage amIKingInRegion: "+kingdom);
		AoIManager.printKingInfo("SubscriberMessage");
		if(AoIManager.amIKingInRegion(kingdom))
		{
			Client c=new Client(name, id, mTargetAddress, teamid);
			if(SharedMemory.getInstance().getClientById(c.getId())==null)
			{
				SharedMemory.getInstance().addClient(c);
				System.out.println("[SubscriberMessage] Creating client. We didn't know him");
			}
			else System.out.println("[SubscriberMessage] Client already known.");
			AoIManager.addSlave(c.getId());
			
			mSendData=new byte[calculateSizeAnswer(id,teamid)];
			byte []value=NetworkUtils.int32ToByte(KayaoValues.MAGIC_NUMBER);
			System.arraycopy(value, 0, mSendData, 0, 4);
			mSendData[4]=KayaoValues.SUSCRIPTION_REQUEST_ANSWER;
			NetworkUtils.insertIntToByteArray(mSendData, 5, counter);
			int index=9;
			index=insertTeammates(mSendData,index,id,teamid);
			index=insertEnemies(mSendData,index,teamid);	
		}
		else
		{
			System.out.println("*** CREATING NEGATIVE ANSWER MESSAGE");
			//if there's not a king anymore
			mSendData=new byte[9];
			byte []value=NetworkUtils.int32ToByte(KayaoValues.MAGIC_NUMBER);
			System.arraycopy(value, 0, mSendData, 0, 4);
			mSendData[4]=KayaoValues.SUSCRIPTION_REQUEST_NEGATIVE_ANSWER;
			NetworkUtils.insertIntToByteArray(mSendData, 5, counter);
		}
	}
	/**
	 * It calculates the size of the answer
	 * @param id
	 * @param teamid
	 * @return the amount of bytes
	 */
	private int calculateSizeAnswer(int id, int teamid) 
	{
		int size=0;
		//each client has 9+length
		for(int i=0;i<AoIManager.getSlavesList().size();i++)
		{
			if(SharedMemory.getInstance().getClientById(AoIManager.getSlavesList().get(i)).getTeam()!=teamid){
				Client cl = SharedMemory.getInstance().getClientById(AoIManager.getSlavesList().get(i));
				String name = cl.getName();
				int len = name.length();
				size+=(9+len);
			}
			else if(SharedMemory.getInstance().getClientById(AoIManager.getSlavesList().get(i)).getId()!=id )
				size+=4;
		}
		// +  headers + n� teammates + n enemies
		return size+9+2+2;
	}

	/**
	 * Insert the correspondent data for the enemies in the byte array
	 * @param data
	 * @param index
	 * @param teamid
	 * @return the new index
	 */
	private int insertEnemies(byte[] data, int index, byte teamid) 
	{
		//We cover the enemies inserting their information
		int n=0;
		//System.out.println("Size of slave vector: " + slaves.size());
		for(int i=0;i<AoIManager.getSlavesList().size();i++)
			if(SharedMemory.getInstance().getClientById(AoIManager.getSlavesList().get(i)).getTeam()!=teamid) 
				n++;
		byte []value=NetworkUtils.int32To2Bytes(n);
		System.arraycopy(value,0,data,index, 2);
		//System.out.println("Index of no of enemies: " + index);
		index+=2;

		for(int i=0;i<AoIManager.getSlavesList().size();i++)
		{
			Client c=SharedMemory.getInstance().getClientById(AoIManager.getSlavesList().get(i));
			if(c.getTeam()!=teamid)
			{

				//System.out.println("Writing enemies");
				byte []clientBytes=c.getBytes();
				System.arraycopy(clientBytes,1,data,index, clientBytes[0]);
				index+=clientBytes[0];
			}
		}

		return index;
	}

	/**
	 * It inserts in the data array the teammates' ids
	 * @param data
	 * @param index
	 * @param id
	 * @param teamid
	 * @return the new index
	 */
	private int insertTeammates(byte[] data, int index, int id, byte teamid)
	{
		int n=0;
		for(int i=0;i<AoIManager.getSlavesList().size();i++)
			if(SharedMemory.getInstance().getClientById(AoIManager.getSlavesList().get(i)).getTeam()==teamid)
				if(SharedMemory.getInstance().getClientById(AoIManager.getSlavesList().get(i)).getId()!=id )
					n++;
		byte []value=NetworkUtils.int32To2Bytes(n);
		System.arraycopy(value,0,data,index, 2);
		index+=2;

		//We cover the teammates inserting the number of them (short) and their id (int32)
		for(int i=0;i<AoIManager.getSlavesList().size();i++)
		{
			Client c=SharedMemory.getInstance().getClientById(AoIManager.getSlavesList().get(i));
			if(c.getTeam()==teamid && c.getId()!=id )
			{
				value=NetworkUtils.int32ToByte(c.getId());
				//System.out.println("Inserting: "+c.getId()+" In: "+index);
				System.arraycopy(value,0,data,index,4);
				//System.out.println("Reading: "+NetworkUtils.insertByteArrayToInt(data, index));
				index+=4;
			}
		}

		return index;
	}
}
